package org.torproject.jtor.crypto;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PEMWriter;
import org.torproject.jtor.TorException;
import org.torproject.jtor.TorParsingException;
import org.torproject.jtor.data.HexDigest;
public class TorPrivateKey {
static public TorPrivateKey generateNewKeypair() {
KeyPairGenerator generator = createGenerator();
generator.initialize(1024, new SecureRandom());
KeyPair pair = generator.generateKeyPair();
return new TorPrivateKey((RSAPrivateKey)pair.getPrivate(), (RSAPublicKey)pair.getPublic());
}
static KeyPairGenerator createGenerator() {
try {
return KeyPairGenerator.getInstance("RSA", "BC");
} catch (NoSuchAlgorithmException e) {
throw new TorException(e);
} catch (NoSuchProviderException e) {
throw new TorException(e);
}
}
public String toPEMFormat(){
final StringWriter stringWriter = new StringWriter();
final PEMWriter pemWriter = new PEMWriter(stringWriter);
try {
pemWriter.writeObject(privateKey);
pemWriter.flush();
} catch (IOException e) {
throw new TorException(e);
}
return stringWriter.toString();
}
static public TorPrivateKey createFromPEMBuffer(String buffer) {
final PEMReader pemReader = new PEMReader(new StringReader(buffer));
final KeyPair kp = readPEMKeyPair(pemReader);
if(kp.getPublic() instanceof RSAPublicKey && kp.getPrivate() instanceof RSAPrivateKey)
return new TorPrivateKey((RSAPrivateKey)kp.getPrivate(), (RSAPublicKey)kp.getPublic());
else
throw new TorParsingException("Failed to extract PEM private key");
}
static private KeyPair readPEMKeyPair(PEMReader reader) {
try {
final Object ob = reader.readObject();
return verifyObjectAsKeyPair(ob);
} catch (IOException e) {
throw new TorException(e);
}
}
static private KeyPair verifyObjectAsKeyPair(Object ob) {
if(ob instanceof KeyPair)
return ((KeyPair)ob);
else
throw new TorParsingException("Failed to extract PEM private key");
}
private final TorPublicKey publicKey;
private final RSAPrivateKey privateKey;
TorPrivateKey(RSAPrivateKey privateKey, RSAPublicKey publicKey) {
this.privateKey = privateKey;
this.publicKey = new TorPublicKey(publicKey);
}
public TorPublicKey getPublicKey() {
return publicKey;
}
public RSAPublicKey getRSAPublicKey() {
return publicKey.getRSAPublicKey();
}
public RSAPrivateKey getRSAPrivateKey() {
return privateKey;
}
private HexDigest keyFingerprint = null;
public HexDigest getFingerprint() {
if(keyFingerprint == null)
keyFingerprint = HexDigest.createDigestForData(toASN1Raw());
return keyFingerprint;
}
private byte[] toASN1Raw() {
byte[] encoded = privateKey.getEncoded();
ASN1InputStream asn1input = new ASN1InputStream(encoded);
try {
PrivateKeyInfo info = PrivateKeyInfo.getInstance(asn1input.readObject());
return info.getDEREncoded();
} catch (IOException e) {
throw new TorException(e);
}
}
}